/*
 * @file: Record helper
 *
 */
#ifndef	__RECORD_HELPER_HPP
#define	__RECORD_HELPER_HPP

#include "opapi.h"
#include <magus/utils/ReadHandle.hpp>

using namespace magus;

// root info
inline void rootGet(const char *buf, RootInfo &info)
{
    int off = 0;
    info.id = longGet(buf, off); 
    off += 4;
    memcpy(info.name, buf+off, OP_NAME_LEN);
    info.name[OP_NAME_LEN] = 0;
    off += OP_NAME_LEN;
    memcpy(info.desc, buf+off, OP_DESC_LEN);
    info.desc[OP_DESC_LEN] = 0;
    off += OP_DESC_LEN;
    info.unit_limit = longGet(buf, off);
    off += 4;
    info.node_limit = longGet(buf, off);
    off += 4;
    info.point_limit = longGet(buf, off);
}

inline void rootStore(char *buf, const RootInfo &info)
{
    int off = 0;
    longStore(buf+off, info.id); 
    off += 4;
    memcpy(buf+off, info.name, OP_NAME_LEN);
    off += OP_NAME_LEN;
    memcpy(buf+off, info.desc, OP_DESC_LEN);
    off += OP_DESC_LEN;
    longStore(buf+off, info.unit_limit);
    off += 4;
    longStore(buf+off, info.node_limit);
    off += 4;
    longStore(buf+off, info.point_limit);
}


// unit info
inline void unitGet(const char *buf, UnitInfo &info)
{
    int off = 0;
    info.id = longGet(buf, off); 
    off += 4;
    memcpy(info.name, buf+off, OP_NAME_LEN);
    info.name[OP_NAME_LEN] = 0;
    off += OP_NAME_LEN;
    memcpy(info.desc, buf+off, OP_DESC_LEN);
    info.desc[OP_DESC_LEN] = 0;
}

inline void unitStore(char *buf, const UnitInfo &info)
{
    int off = 0;
    longStore(buf+off, info.id); 
    off += 4;
    memcpy(buf+off, info.name, OP_NAME_LEN);
    off += OP_NAME_LEN;
    memcpy(buf+off, info.desc, OP_DESC_LEN);
}


// node info
inline void nodeGet(const char *buf, NodeInfo &info)
{
    int off = 0;
    info.id = longGet(buf, off); 
    off += 4;
    info.parent_id = longGet(buf, off); 
    off += 4;
    info.type = longGet(buf, off); 
    off += 4;
    memcpy(info.name, buf+off, OP_NAME_LEN);
    info.name[OP_NAME_LEN] = 0;
    off += OP_NAME_LEN;
    memcpy(info.desc, buf+off, OP_DESC_LEN);
    info.desc[OP_DESC_LEN] = 0;
    off += OP_DESC_LEN;
    info.freq = longGet(buf, off); 
    off += 4;
    info.compress = longGet(buf, off); 
    off += 4;
    info.access_time = longGet(buf, off); 
}

inline void nodeStore(char *buf, const NodeInfo &info)
{
    int off = 0;
    longStore(buf+off, info.id); 
    off += 4;
    longStore(buf+off, info.parent_id); 
    off += 4;
    longStore(buf+off, info.type); 
    off += 4;
    memcpy(buf+off, info.name, OP_NAME_LEN);
    off += OP_NAME_LEN;
    memcpy(buf+off, info.desc, OP_DESC_LEN);
    off += OP_DESC_LEN;
    longStore(buf+off, info.freq); 
    off += 4;
    longStore(buf+off, info.compress); 
    off += 4;
    timeStore(buf+off, info.access_time); 
    off += 4;
}


// point info
inline void pointGet(const char *buf, PointInfo *ppi, bool hasID = false)
{
	// Total: 138 + 12 + 44 + 6 = 200 bytes;

	// common informations - 17 fields, 10+108+8+4+8 = 138 bytes
	if (!hasID)
    	ppi->id = longGet(buf, 0); 
    ppi->parent_id = longGet(buf, 4); 
    ppi->point_type = buf[8]; 
    ppi->record_type = buf[9]; 
    memcpy(ppi->name, buf+10, OP_PN_LEN);
    ppi->name[OP_PN_LEN] = 0;
    memcpy(ppi->alias, buf+40, OP_PN_LEN);
    ppi->alias[OP_PN_LEN] = 0;
    memcpy(ppi->desc, buf+70, OP_DESC_LEN);
    ppi->desc[OP_DESC_LEN] = 0;
    memcpy(ppi->charst, buf+102, OP_CHAR_LEN);
    ppi->charst[OP_CHAR_LEN] = 0;
    ppi->freq = shortGet(buf, 118); 
    ppi->ctrl = shortGet(buf, 120); 
    ppi->location = longGet(buf, 122); 
    ppi->channel = buf[126]; 
    ppi->alarm_type = buf[127]; 
    ppi->alarm_prior = buf[128]; 
    ppi->archived = buf[129]; 
    ppi->flags = longGet(buf, 130); 
    ppi->create_time = longGet(buf, 134); 
    
	// DX fields - 2 fields, 12 bytes
    memcpy(ppi->set, buf+138, OP_ST_LEN);
    ppi->set[OP_ST_LEN] = 0;
    memcpy(ppi->reset, buf+144, OP_ST_LEN);
    ppi->reset[OP_ST_LEN] = 0;
    
	// AX fields - 12 fields, 44 bytes              
    memcpy(ppi->eu, buf+150, OP_EU_LEN);
    ppi->eu[OP_EU_LEN] = 0;
    ppi->format = shortGet(buf, 158); 
    ppi->iv = floatGet(buf, 160); 
    ppi->bv = floatGet(buf, 164); 
    ppi->tv = floatGet(buf, 168); 
    ppi->ll = floatGet(buf, 172); 
    ppi->hl = floatGet(buf, 176); 
    ppi->zl = floatGet(buf, 180); 
    ppi->zh = floatGet(buf, 184); 
    ppi->deadband = floatGet(buf, 188); 
    ppi->db_type = buf[192]; 
    ppi->comp_type = buf[193]; 
    
	// stat & calc - 5 fields, 6 bytes             
    ppi->stat_type = buf[194]; 
    ppi->period = shortGet(buf, 195); 
    ppi->offset = shortGet(buf, 197); 
    ppi->calc_type = buf[199]; 
    ppi->expression = NULL;
}

inline void pointStore(char *buf, const PointInfo &info)
{
	// Total: 138 + 12 + 44 + 6 = 200 bytes;

	// common informations - 17 fields, 10+100+6+4+8 = 128 bytes
    longStore(buf, info.id); 
    longStore(buf+4, info.parent_id); 
    buf[8] = info.point_type;
    buf[9] = info.record_type;
    memcpy(buf+10, info.name, OP_PN_LEN);
    memcpy(buf+40, info.alias, OP_PN_LEN);
    memcpy(buf+70, info.desc, OP_DESC_LEN);
    memcpy(buf+102, info.charst, OP_CHAR_LEN);
    shortStore(buf+118, info.freq); 
    shortStore(buf+120, info.ctrl); 
    longStore(buf+122, info.location); 
    buf[126] = info.channel;
    buf[127] = info.alarm_type;
    buf[128] = info.alarm_prior;
    buf[129] = info.archived;
    longStore(buf+130, info.flags); 
    longStore(buf+134, info.create_time); 
    
	// DX fields - 2 fields, 12 bytes
    memcpy(buf+138, info.set, OP_ST_LEN);
    memcpy(buf+144, info.reset, OP_ST_LEN);
    
	// AX fields - 12 fields, 44 bytes              
    memcpy(buf+150, info.eu, OP_EU_LEN);
    shortStore(buf+158, info.format); 
    floatStore(buf+160, info.iv); 
    floatStore(buf+164, info.bv); 
    floatStore(buf+168, info.tv); 
    floatStore(buf+172, info.ll); 
    floatStore(buf+176, info.hl); 
    floatStore(buf+180, info.zl); 
    floatStore(buf+184, info.zh); 
    floatStore(buf+188, info.deadband); 
    buf[192] = info.db_type;
    buf[193] = info.comp_type;
    
	// stat & calc - 5 fields, 10 bytes             
    buf[194] = info.stat_type;
    shortStore(buf+195, info.period); 
    shortStore(buf+197, info.offset); 
    buf[199] = info.calc_type;
}


// Calc Expression
inline void itemGet(char *buf, ExInfo *p)
{
    p->rid = longGet(buf, 0);
    p->id = longGet(buf, 4);
    memcpy(p->expression, buf+8, OP_EX_LEN-1);
    p->expression[OP_EX_LEN-1] = '\0';
}

inline void itemStore(char *buf, const ExInfo &info)
{
    longStore(buf, info.rid);
    longStore(buf+4, info.id);
    memcpy(buf+8, info.expression, OP_EX_LEN-1);
    buf[8+OP_EX_LEN-1] = '\0';
}


#endif  // #ifndef __RECORD_HELPER_HPP
